﻿using System;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using System.Web;
using System.IO;
using System.IO.Compression;


/// <summary>
///WebUtility 的摘要说明
/// </summary>
public class WebUtility
{
    private const int iBuffRowCount = 10;

    #region Export for DataTable
    public static void ExportToExcel(DataTable dt, HttpResponse Response, string title)
    {
        ExportToExcel(dt, Response, title, null);
    }
    public static void ExportToExcel(DataTable dt, HttpResponse Response, string title, string[,] DataFields)
    {
        ExportToExcel(dt, Response, title, DataFields, null);
    }
    public static void ExportToExcel(DataTable dt, HttpResponse Response, string title, string[,] DataFields, DataTable dtSummary)
    {
        string filename = title + DateTime.Now.ToString("yyyyMMddHHmmss");
        Response.Clear();
        Response.Buffer = false;
        Response.Cookies["cokExport"].Value = "ok";
        Response.AppendHeader("Content-Disposition", "attachment;filename=" + filename + ".xls");
        Response.ContentType = "application/ms-excel";
        Response.Write(@"<html><head><meta http-equiv=""Content-Type"" content=""text/html; charset=utf-8"" /><style> .text { mso-number-format:\@; } </style></head><body>");

        ExportToHTML(dt, Response, title, DataFields, dtSummary);

        Response.Write("</body></html>");
        Response.End();
    }
    public static void ExportToHTML(DataTable dt, HttpResponse Response, string title, string[,] DataFields)
    {
        ExportToHTML(dt, Response, title, DataFields, null);
    }
    public static void ExportToHTML(DataTable dt, HttpResponse Response, string title, string[,] DataFields, DataTable dtSummary)
    {
        bool NoDataFields = (DataFields == null);
        bool StyleText = (!NoDataFields && DataFields.GetLength(1) == 3);

        int colCount = NoDataFields ? dt.Columns.Count : DataFields.GetLength(0);

        StringBuilder str = new StringBuilder(1024 * iBuffRowCount);

        str.Append("<table border=\"1\">\r\n<tr style=\"color:White;background-color:#000088;\">");
        for (int c = 0; c < colCount; c++)
        {
            str.Append("<td>");
            str.Append(NoDataFields ? dt.Columns[c].ColumnName : DataFields[c, 1]);
            str.Append("</td>");
        }
        str.AppendLine("</tr>");

        int iRowCount = 0;
        foreach (DataRow dr in dt.Rows)
        {
            str.Append("<tr>");
            for (int c = 0; c < colCount; c++)
            {
                if (StyleText && DataFields[c, 2] != "")
                {
                    if (DataFields[c, 2] == "@")
                    {
                        str.Append("<td class='text'>");
                        str.Append(NoDataFields ? dr[c].ToString().Trim() : dr[DataFields[c, 0]].ToString().Trim());
                    }
                    else
                    {
                        str.Append("<td>");
                        str.Append(NoDataFields ? string.Format(DataFields[c, 2], dr[c]) : string.Format(DataFields[c, 2], dr[DataFields[c, 0]]));
                    }
                }
                else
                {
                    str.Append("<td>");
                    str.Append(NoDataFields ? dr[c].ToString().Trim() : dr[DataFields[c, 0]].ToString().Trim());
                }
                str.Append("</td>");
            }
            str.AppendLine("</tr>");
            iRowCount++;
            if (iRowCount >= iBuffRowCount)
            {
                Response.Write(str.ToString());
                str.Length = 0;
                iRowCount = 0;
            }
        }
        #region begin output summary line.
        if (dtSummary != null)
        {
            int SumColCount = 0;
            if (dtSummary.Rows.Count > 0)
            {
                SumColCount = dtSummary.Columns.Count;
                if (colCount < SumColCount) SumColCount = colCount;
            }
            str.Append("<tr>");
            for (int c = 0; c < SumColCount; c++)
            {
                str.Append("<td style=\"background-color:#CCCCFF;\">");
                str.Append(dtSummary.Rows[0][c].ConvertObjToStr().Trim());
                str.Append("</td>");
            }
            str.AppendLine("</tr>");
        }
        #endregion
        str.AppendLine("</table>");
        Response.Write(str.ToString());
    }
    #endregion

    #region Export for DataTable (.zip format)
    public static void ExportToZip(DataTable dt, HttpResponse Response, string title)
    {
        ExportToZip(dt, Response, title, null);
    }
    public static void ExportToZip(DataTable dt, HttpResponse Response, string title, string[,] DataFields)
    {
        ExportToZip(dt, Response, title, DataFields, null);
    }
    public static void ExportToZip(DataTable dt, HttpResponse Response, string title, string[,] DataFields, DataTable dtSummary)
    {
        bool NoDataFields = (DataFields == null);
        bool StyleText = (!NoDataFields && DataFields.GetLength(1) == 3);

        int colCount = NoDataFields ? dt.Columns.Count : DataFields.GetLength(0);

        StringBuilder str = new StringBuilder(1024 * iBuffRowCount);
        MemoryStream ms = new MemoryStream();
        GZipStream compressedzipStream = new GZipStream(ms, CompressionMode.Compress, true);

        str.AppendLine(@"<html><head><meta http-equiv=""Content-Type"" content=""text/html; charset=utf-8"" /><style> .text { mso-number-format:\@; } </style></head><body>");
        str.Append("<table border=\"1\">\r\n<tr style=\"color:White;background-color:#000088;\">");
        for (int c = 0; c < colCount; c++)
        {
            str.Append("<td>");
            str.Append(NoDataFields ? dt.Columns[c].ColumnName : DataFields[c, 1]);
            str.Append("</td>");
        }
        str.AppendLine("</tr>");
        byte[] buffer;
        int iRowCount = 0;
        foreach (DataRow dr in dt.Rows)
        {
            str.Append("<tr>");
            for (int c = 0; c < colCount; c++)
            {
                if (StyleText && DataFields[c, 2] != "")
                {
                    if (DataFields[c, 2] == "@")
                    {
                        str.Append("<td class='text'>");
                        str.Append(NoDataFields ? dr[c].ToString().Trim() : dr[DataFields[c, 0]].ToString().Trim());
                    }
                    else
                    {
                        str.Append("<td>");
                        str.Append(NoDataFields ? string.Format(DataFields[c, 2], dr[c]) : string.Format(DataFields[c, 2], dr[DataFields[c, 0]]));
                    }
                }
                else
                {
                    str.Append("<td>");
                    str.Append(NoDataFields ? dr[c].ToString().Trim() : dr[DataFields[c, 0]].ToString().Trim());
                }
                str.Append("</td>");
            }
            str.AppendLine("</tr>");
            iRowCount++;
            if (iRowCount >= iBuffRowCount)
            {
                buffer = System.Text.Encoding.UTF8.GetBytes(str.ToString());
                compressedzipStream.Write(buffer, 0, buffer.Length);
                str.Length = 0;
                iRowCount = 0;
            }
        }
        #region begin output summary line.
        if (dtSummary != null)
        {
            int SumColCount = 0;
            if (dtSummary.Rows.Count > 0)
            {
                SumColCount = dtSummary.Columns.Count;
                if (colCount < SumColCount) SumColCount = colCount;
            }
            str.Append("<tr>");
            for (int c = 0; c < SumColCount; c++)
            {
                str.Append("<td style=\"background-color:#CCCCFF;\">");
                str.Append(dtSummary.Rows[0][c].ConvertObjToStr().Trim());
                str.Append("</td>");
            }
            str.AppendLine("</tr>");
        }
        #endregion
        str.AppendLine("</table></body></html>");
        buffer = System.Text.Encoding.UTF8.GetBytes(str.ToString());
        compressedzipStream.Write(buffer, 0, buffer.Length);
        compressedzipStream.Close();
        compressedzipStream.Dispose();

        string filename = title + DateTime.Now.ToString("yyyyMMddHHmmss");
        Response.Clear();
        Response.Buffer = false;
        Response.Cookies["cokExport"].Value = "ok";
        Response.AppendHeader("Content-Disposition", "attachment;filename=" + filename + ".zip");

        // 输出zip文件头
        ms.Position = 0;
        byte[] header = new byte[10];
        ms.Read(header, 0, 10);
        header[3] = 8;        //表示包含文件名信息
        Response.BinaryWrite(header);
        Response.BinaryWrite(System.Text.Encoding.Default.GetBytes(filename + ".xls"));
        byte[] byte0 = new byte[1];
        byte0[0] = 0;
        Response.BinaryWrite(byte0);

        // 输出压缩后的文件内容
        ResponseWriteMemoryStream(ms, Response);
        ms.Close();
        ms.Dispose();
        Response.End();
    }
    #endregion
    public static void ResponseWriteMemoryStream(MemoryStream ms, HttpResponse Response)
    {
        const int bufferLength = 10240;
        byte[] fileContent = new byte[bufferLength];
        int count = 0;
        while (true)
        {
            count = ms.Read(fileContent, 0, bufferLength);
            if (count < bufferLength)
            {
                if (count > 0)
                {
                    byte[] fileContentEnd = new byte[count];
                    Array.Copy(fileContent, fileContentEnd, count);
                    Response.BinaryWrite(fileContentEnd);
                }
                break;
            }
            else
            {
                Response.BinaryWrite(fileContent);
            }
        }
    }
    #region Export for SqlDataReader
    public static void ExportToExcel(SqlDataReader dt, HttpResponse Response, string title)
    {
        ExportToExcel(dt, Response, title, null);
    }
    public static void ExportToExcel(SqlDataReader dt, HttpResponse Response, string title, string[,] DataFields)
    {
        ExportToHTML(dt, Response, title, DataFields);
    }
    public static void ExportToHTML(SqlDataReader dt, HttpResponse Response, string title, string[,] DataFields)
    {
        bool NoDataFields = (DataFields == null);

        string filename = title + DateTime.Now.ToString("yyyyMMddHHmmss");
        Response.Clear();
        Response.Buffer = false;
        Response.AppendHeader("Content-Disposition", "attachment;filename=" + filename + ".xls");
        Response.ContentType = "application/ms-excel";
        Response.Write(@"<html><head><meta http-equiv=""Content-Type"" content=""text/html; charset=utf-8"" /><style> .text { mso-number-format:\@; } </style></head><body>");
        Response.Write("<table border=\"1\">\r\n");

        int colCount = NoDataFields ? dt.FieldCount : DataFields.GetLength(0);

        StringBuilder str = new StringBuilder(1024 * iBuffRowCount);

        str.Append("<tr style=\"color:White;background-color:#000088;\">");
        if (NoDataFields)
        {
            DataTable dtSchema = dt.GetSchemaTable();
            foreach (DataRow dr in dtSchema.Rows)
            {
                str.Append("<td>");
                str.Append(dr["ColumnName"]);
                str.Append("</td>");
            }
        }
        else
        {
            for (int c = 0; c < colCount; c++)
            {
                str.Append("<td>");
                str.Append(DataFields[c, 1]);
                str.Append("</td>");
            }
        }
        str.AppendLine("</tr>");

        int iRowCount = 0;
        while (dt.Read())
        {
            str.Append("<tr>");
            for (int c = 0; c < colCount; c++)
            {
                str.Append("<td>");
                str.Append(NoDataFields ? dt[c].ToString().Trim() : dt[DataFields[c, 0]].ToString().Trim());
                str.Append("</td>");
            }
            str.AppendLine("</tr>");
            iRowCount++;
            if (iRowCount >= iBuffRowCount)
            {
                Response.Write(str.ToString());
                str.Length = 0;
                iRowCount = 0;
            }
        }
        str.AppendLine("</table></body></html>");
        Response.Write(str.ToString());
    }
    #endregion
}
